/**
 * @file spec interface
 * @author fanxueliang@qq.com
 */

import type {ExtraAttr} from './extraAttr';

export type StringOrNumber = string | number;
export type RulesKey = keyof RulesItem;

export interface TagListRules {
    a?: RulesItem;
    em?: RulesItem;
    br?: RulesItem;
}

export interface RegexRules {
    pattern: string;
    modifiers?: string;
    errorText?: string;
}

// 2.0版本的表达式
export interface ExpressionProps {
    // 操作符
    operation: string;
    // 源节点路径
    sourcePath: string;
    // 目标节点路径
    targetValue?: string;
    // 目标节点值
    targetPath?: string;
    // 逻辑操作符
    logicOp: string;
}

export interface EnumValuesSpecItem {
    'value': string;
    'displayName': string;
    'items'?: UnionSpecItem[];
    ':hidden'?: string;
    'hiddenExpression'?: string[];
}

export type UnionSpecItem =
    | ObjectSpecItem
    | ListSpecItem
    | UrlSpecItem
    | HtmlSpecItem
    | UploadSpecItem
    | VideoUploadSpecItem
    | AudioUploadSpecItem
    | NumberSpecItem
    | BoolSpecItem
    | StringSpecItem
    | ColorSpecItem
    | EnumSpecItem
    | AlternativeSpecItem
    | ActionLinkSpecItem;

/** the property 「rules」 of SpecItem */
export interface RulesItem {
    /** about telephone */
    // 固定电话
    telephone?: boolean;
    // 传真
    fax?: boolean;
    // 移动电话
    mobilephone?: boolean;
    // 企业/商业电话
    businessPhone?: boolean;
    // 所有电话
    phone?: boolean;

    /** about count */
    count?: number;
    minCount?: number;
    maxCount?: number;
    multipleCount?: number;

    /** about Length */
    minByteLength?: number;
    maxByteLength?: number;
    maxTextByteLength?: number;
    minTextByteLength?: number;
    fixLength?: number;
    fixByteLength?: number;
    minLength?: number;
    maxLength?: number;

    /** about Date */
    date?: {
        format?: string;
        gt?: string;
        lt?: string;
    };
    /** about Url */
    link?: boolean;
    imageUrl?: boolean;
    flvUrl?: boolean;
    flashUrl?: boolean;
    videoUrl?: boolean;
    audioUrl?: boolean;
    notLink?: boolean;
    appScheme?: boolean;

    /** about Number Type */
    int?: boolean;
    number?: boolean;
    min?: number;
    max?: number;
    gt?: number;
    lt?: number;
    precision?: number;
    maxPrecision?: number;

    required?: boolean;
    regex?: RegexRules;
    jsRule?: string;
    inEnum?: StringOrNumber[];
    email?: boolean;
    maxLineCount?: number;
    tagList?: TagListRules;
    excludesLinkTag?: boolean;
}

export interface BasicSpecItem {
    'name': string;
    'idx'?: string;
    'displayName'?: string;
    'dataType': string;
    'display'?: string;
    'readOnly'?: boolean;
    'disabled'?: boolean;
    'tip'?: string;
    'descriptionTip'?: string;
    'nameTip'?: string;
    'rules'?: RulesItem;
    'needFilled'?: boolean;
    'fieldRemove'?: boolean;
    ':hidden'?: string;
    ':remove'?: string;
    'removeExpression'?: ExpressionProps[];
    'hiddenExpression'?: ExpressionProps[];
}

export interface StringSpecItem extends BasicSpecItem {
    dataType: 'STRING';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    multiline?: boolean;
    ui?:
        | 'Input'
        | 'Textarea'
        | 'SearchBox'
        | 'RadioButtonGroup'
        | 'Uploader'
        | 'VideoUploader'
        | 'RichText'
        | 'DatePicker'
        | 'SearchBox'
        | 'Autocomplete';
    enumValues?: EnumValuesSpecItem[];
}

export interface ColorSpecItem extends BasicSpecItem {
    dataType: 'COLOR';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    ui?: 'Color';
}

export interface BoolSpecItem extends BasicSpecItem {
    dataType: 'BOOL';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    ui?: 'Checkbox' | 'Switch';
}

export interface NumberSpecItem extends BasicSpecItem {
    dataType: 'NUMBER';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    ui?: 'NumberInput';
}

// 现在为了兼容老数据，之后要干掉这种类型，并到stringSpec里去
export interface EnumSpecItem extends BasicSpecItem {
    dataType: 'ENUM';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    enumValues?: EnumValuesSpecItem[];
    ui?: 'EnumSelect' | 'RadioButtonGroup' | 'CheckboxGroup';
}

// 现在为了兼容老数据，之后要干掉这种类型，并到stringSpec里去
export interface UploadSpecItem extends BasicSpecItem {
    dataType: 'UPLOAD';
    defaultValue?: string;
    extraAttr?: ExtraAttr['image'];
    ui?: 'Uploader';
}

// 现在为了兼容老数据，之后要干掉这种类型，并到stringSpec里去
export interface VideoUploadSpecItem extends BasicSpecItem {
    dataType: 'VIDEO';
    defaultValue?: string;
    extraAttr?: ExtraAttr['video'];
    ui?: 'VideoUploader';
}

// 现在为了兼容老数据，之后要干掉这种类型，并到stringSpec里去
export interface AudioUploadSpecItem extends BasicSpecItem {
    dataType: 'AUDIO';
    defaultValue?: string;
    extraAttr?: ExtraAttr['audio'];
    ui?: 'AudioUploader';
}

// 现在为了兼容老数据，之后要干掉这种类型，并到stringSpec里去
export interface HtmlSpecItem extends BasicSpecItem {
    dataType: 'HTML';
    defaultValue?: string;
    multiline?: boolean;
    extraAttr?: ExtraAttr['html'];
    ui?: 'RichText';
}

// 现在为了兼容老数据，之后要干掉这种类型，并到stringSpec里去
export interface UrlSpecItem extends BasicSpecItem {
    dataType: 'URL';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    ui?: 'Input';
}

export interface ObjectSpecItem extends BasicSpecItem {
    dataType: 'OBJECT';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    items?: UnionSpecItem[];
    ui?: 'Block';
}

export interface ListSpecItem extends BasicSpecItem {
    dataType: 'LIST';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    items?: UnionSpecItem[];
    element?: UnionSpecItem;
    ui?: 'List' | 'Tabs';
}

// 现在为了兼容老数据，之后要干掉这种类型
// 以后新的用datatype: Object & ui: select来代替
export interface AlternativeSpecItem extends BasicSpecItem {
    dataType: 'ALTERNATIVE';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    enumValues?: EnumValuesSpecItem[];
    ui?: 'Select';
}

// ActionLinkSpecItem是虚拟spec节点（转换过程的中间节点），
// 只存在于渲染组件spec中，只对spec可视化sdk配置起作用
// 最终会被平台转换成AlternativeSpecItem
export interface ActionLinkSpecItem extends BasicSpecItem {
    dataType: 'OWNACTIONLINK';
    defaultValue?: string;
    extraAttr?: ExtraAttr['basic'];
    enumValues?: EnumValuesSpecItem[];
    ui?: 'Select';
}
